<?php

namespace App\Services\WechatApi\UnifiedOrder;

use App\Services\ServiceBase;
use Illuminate\Support\Facades\Http;
use YQ\YqCurl;
use YQ\YqExtend;

// 统一下单
class UnifiedOrder extends ServiceBase
{
    public function getSign($appkey, $params)
    {
        $arr = [];
        ksort($params);
        foreach ($params as $key => $val) {
            if ($key === 'sign') continue;
            if ($val === '' || $val === 'null' || $val === 'undefined' || is_null($val)) continue;
            $arr[] = "$key=$val";
        }
        $str  = implode("&", $arr) . "&key={$appkey}";
        $sign = strtoupper(md5($str));

        return $sign;
    }

    // 将数据转为xml字符串
    public function toXml(array $data)
    {
        $xml = "<xml>";
        foreach ($data as $key => $val) {
            if (is_numeric($val)) {
                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
            } else {
                $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
            }
        }
        $xml .= "</xml>";
        return $xml;
    }

    // 将xml转为array
    public function fromXml(string $xml)
    {
        $xml = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
        $json = json_encode($xml);
        $data = json_decode($json, true);

        return $data;
    }

    // 统一下单接口
    // 应用场景 JSAPI--JSAPI支付（或小程序支付）、NATIVE--Native支付、APP--app支付，MWEB--H5支付
    // https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
    public function createOrder($appid, $mch_key, $mch_id, $trade_type, $data)
    {
        // 必填参数
        $params = [
            'appid'        => $appid, //公众账号ID
            'mch_id'       => $mch_id, //商户号
            'nonce_str'    => YqExtend::uniqid32(), //随机字符串
            'body'         => $data['body'], //商品描述
            'out_trade_no' => $data['out_trade_no'], //我方订单
            'total_fee'    => $data['total_fee'], //价格 分
            'notify_url'   => $data['notify_url'], //充值成功回调地址
            'trade_type'   => $trade_type, //交易类型 JSAPI，NATIVE，APP，MWEB
            'attach'       => $data['attach'], //附加数据，在查询API和支付通知中原样返回，可作为自定义参数使用。
        ];

        // 针对不同的下单类型进行参数设置
        switch ($trade_type) {
            case 'JSAPI':
                $params['spbill_create_ip'] = YqExtend::getIP(); // 客户端ip
                $params['openid']           = $data['openid']; // 用户openid
                break;
            case 'APP':
                $params['spbill_create_ip'] = YqExtend::getIP(); // 客户端ip
                break;
            case 'NATIVE':
                $params['spbill_create_ip'] = YqExtend::getServerIp(); // 服务端ip
                break;
            case 'MWEB':
                $params['spbill_create_ip'] = YqExtend::getIP(); // 客户端ip
                $params['scene_info']       = $data['scene_info']; // 场景信息
                break;
        }

        // 签名
        $params['sign'] = $this->getSign($mch_key, $params);

        $xml  = $this->toXml($params);
        $url  = "https://api.mch.weixin.qq.com/pay/unifiedorder";

        $response = YqCurl::curl($url, $xml, 1, 1, 10, false);
        if (!$response) {
            return false;
        }

        $res = $this->fromXml($response);
        // 是否请求成功
        if ($res['return_code'] !== 'SUCCESS') {
            yqlog($params, $res);
            return false;
        }

        // 是否下单成功
        if ($res['result_code'] !== 'SUCCESS') {
            yqlog($params, $res);
            return false;
        }

        // 校验签名
        $sign = $this->getSign($mch_key, $res);
        if ($res['sign'] !== $sign) {
            return false;
        }

        return $res;
    }

    // 支付结果通知
    // https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7
    public function payNotify($mch_key, $xml)
    {
        $res = $this->fromXml($xml);
        if (!isset($res['return_code']) || $res['return_code'] != 'SUCCESS') {
            return false;
        }

        // 校验签名
        $sign = $this->getSign($mch_key, $res);
        if ($res['sign'] !== $sign) {
            return false;
        }

        return $res;
    }

    // 处理完结果通知后，返回数据给微信
    public function payNotifyReturn($appkey, $code = 'SUCCESS', $msg = 'OK')
    {
        $params = [
            'return_code' => $code,
            'return_msg'  => $msg,
        ];
        if ($code === 'SUCCESS') {
            $params['sign'] = $this->getSign($appkey, $params);
        }
        $xml = $this->toXml($params);

        return $xml;
    }
}
